package com.supermap.panes;

import com.supermap.analyst.networkanalyst.*;
import com.supermap.consts.AttrConsts;
import com.supermap.data.*;
import com.supermap.mapping.Map;
import com.supermap.mapping.TrackingLayer;
import com.supermap.panes.advance.SettingPane;
import com.supermap.ui.Action;
import com.supermap.ui.MapControl;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class TheBestPathAnalystSettingPane extends SettingPane implements MouseListener {
    private MapControl mapControl;
    private JTable pathGuidesTbl;
    private JSplitPane dataPane;
    private JPopupMenu popupMenu;
    private JButton dynamicBtn;

    private DatasetVector datasetVector;
    private TransportationAnalyst transportationAnalyst;
    private Point2Ds points;
    private Point2Ds barrierPoints;
    private int addPoints;
    private Timer timer;
    private int routePartIndex;
    private int routePartPointIndex;
    private PointMs routePart;

    public TheBestPathAnalystSettingPane(String title, MapControl mapControl, DatasetVector datasetVector, JSplitPane dataPane) {
        super(title, new Object[]{mapControl, datasetVector, dataPane});
    }

    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {
        if (e.getButton() == 1) {
            Point point = new Point(e.getX(), e.getY());
            Map map = mapControl.getMap();
            Point2D mapPoint = map.pixelToMap(point);
            if (map.getBounds().contains(mapPoint)) {
                switch (addPoints) {
                    case 1:
                        addPoint(mapPoint);
                        break;
                    case 2:
                        addBarrierPoints(mapPoint);
                        break;
                    default:
                        break;
                }
            }
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    protected void initializeArgs(Object[] args) {
        this.mapControl = (MapControl) args[0];
        this.datasetVector = (DatasetVector) args[1];
        this.dataPane = (JSplitPane) args[2];
        points = new Point2Ds();
        barrierPoints = new Point2Ds();
        addPoints = 0;
        routePartIndex = 0;
        routePartPointIndex = 0;
        timer = new Timer(500, e -> {
            Map map = mapControl.getMap();
            TrackingLayer trackingLayer = map.getTrackingLayer();
            int routeIndex = trackingLayer.indexOf("Route");
            if (routeIndex == -1) {
                return;
            }
            GeoStyle geoStyle = new GeoStyle();
            geoStyle.setLineColor(Color.BLUE);
            geoStyle.setMarkerSize(new Size2D(9, 9));
            Geometry geometry = trackingLayer.get(routeIndex);
            if (geometry instanceof GeoLineM) {
                GeoLineM route = (GeoLineM) geometry;
                if (routePartIndex >= route.getPartCount()) {
                    routePartIndex = 0;
                }
                routePart = route.getPart(routePartIndex++);
            }
            if (routePart == null) {
                return;
            }
            if (routePartPointIndex >= routePart.getCount()) {
                routePartPointIndex = 0;
            }
            PointM pointM = routePart.getItem(routePartPointIndex++);
            GeoPoint geoPoint = new GeoPoint(new Point2D(pointM.getX(), pointM.getY()));
            geoPoint.setStyle(geoStyle);
            TextPart textPart = new TextPart();
            textPart.setX(geoPoint.getX());
            textPart.setY(geoPoint.getY());
            textPart.setText("行驶位置");
            GeoText geoText = new GeoText(textPart);
            TextStyle textStyle = new TextStyle();
            textStyle.setForeColor(Color.BLUE);
            geoText.setTextStyle(textStyle);
            int dynamicPointIndex = trackingLayer.indexOf("dynamicPosition");
            if (dynamicPointIndex != -1) {
                trackingLayer.remove(dynamicPointIndex);
            }
            int dynamicPositionTextIndex = trackingLayer.indexOf("dynamicPositionText");
            if (dynamicPositionTextIndex != -1) {
                trackingLayer.remove(dynamicPositionTextIndex);
            }
            trackingLayer.add(geoPoint, "dynamicPosition");
            trackingLayer.add(geoText, "dynamicPositionText");
            map.refreshTrackingLayer();
        });
    }

    @Override
    protected void initializeCore() {
        super.confirmBtn.setText("分析");

        transportationAnalyst = new TransportationAnalyst();
        TransportationAnalystSetting transportationAnalystSetting = new TransportationAnalystSetting();
        transportationAnalystSetting.setNetworkDataset(datasetVector);
        WeightFieldInfos weightFieldInfos = new WeightFieldInfos();
        WeightFieldInfo weightFieldInfo = new WeightFieldInfo();
        weightFieldInfo.setFTWeightField("smLength");
        weightFieldInfo.setTFWeightField("smLength");
        transportationAnalystSetting.setEdgeIDField("SmID");
        transportationAnalystSetting.setNodeIDField("SmNodeID");
        transportationAnalystSetting.setFNodeIDField("SmFNode");
        transportationAnalystSetting.setTNodeIDField("SmTNode");
        FieldInfos fieldInfos = datasetVector.getFieldInfos();
        if (Environment.getCurrentCulture().contentEquals("zh-CN")) {
            if (fieldInfos.indexOf("roadName") != -1) {
                transportationAnalystSetting.setEdgeNameField("roadName");
            } else {
                transportationAnalystSetting.setEdgeNameField("name");
            }
        } else {
            if (fieldInfos.indexOf("roadName_en") != -1) {
                transportationAnalystSetting.setEdgeNameField("roadName_en");
            } else {
                transportationAnalystSetting.setEdgeNameField("name_en");
            }
        }
        weightFieldInfo.setName("length");
        weightFieldInfos.add(weightFieldInfo);
        transportationAnalystSetting.setWeightFieldInfos(weightFieldInfos);
        transportationAnalyst.setAnalystSetting(transportationAnalystSetting);
        transportationAnalyst.load();

        mapControl.removeMouseListener(this);
        mapControl.addMouseListener(this);

        JToolBar toolBar = new JToolBar();
        super.mainPanel.add(toolBar, BorderLayout.NORTH);

        JButton addPointBtn = new JButton("添加站点");
        addPointBtn.addActionListener(e -> {
            mapControl.setAction(Action.NULL);
            addPoints = 1;
        });
        toolBar.add(addPointBtn);

        JButton addBarrierPointBtn = new JButton("添加障碍点");
        addBarrierPointBtn.addActionListener(e -> {
            mapControl.setAction(Action.NULL);
            addPoints = 2;
        });
        toolBar.add(addBarrierPointBtn);

        JButton clearBtn = new JButton("清空");
        clearBtn.addActionListener(e -> doClose());
        toolBar.add(clearBtn);

        dynamicBtn = new JButton("开启动态引导");
        super.bottomPanel.add(dynamicBtn, BorderLayout.WEST);
        dynamicBtn.addActionListener(e -> {
            String text = dynamicBtn.getText();
            if (text.equals("开启动态引导")) {
                timer.start();
                dynamicBtn.setText("关闭动态引导");
                confirmBtn.setEnabled(false);
            } else {
                timer.stop();
                routePartIndex = 0;
                routePartPointIndex = 0;
                Map map = mapControl.getMap();
                TrackingLayer trackingLayer = map.getTrackingLayer();
                int dynamicPointIndex = trackingLayer.indexOf("dynamicPosition");
                if (dynamicPointIndex != -1) {
                    trackingLayer.remove(dynamicPointIndex);
                }
                int dynamicPositionTextIndex = trackingLayer.indexOf("dynamicPositionText");
                if (dynamicPositionTextIndex != -1) {
                    trackingLayer.remove(dynamicPositionTextIndex);
                }
                map.refreshTrackingLayer();
                dynamicBtn.setText("开启动态引导");
                confirmBtn.setEnabled(true);
            }
        });
        dynamicBtn.setEnabled(false);
    }

    @Override
    protected void doConfirm() {
        mapControl.setAction(Action.SELECT2);
        TransportationAnalystParameter parameter = new TransportationAnalystParameter();
        parameter.setPoints(points);
        parameter.setBarrierPoints(barrierPoints);
        parameter.setWeightName("length");
        parameter.setNodesReturn(true);
        parameter.setEdgesReturn(true);
        parameter.setPathGuidesReturn(true);
        parameter.setRoutesReturn(true);
        TransportationAnalystResult pathResult = transportationAnalyst.findPath(parameter, false);

        addPoints = 0;

        Map map = mapControl.getMap();
        TrackingLayer trackingLayer = map.getTrackingLayer();
        int routeIndex = trackingLayer.indexOf("Route");
        if (routeIndex != -1) {
            trackingLayer.remove(routeIndex);
        }

        GeoStyle geoStyle = new GeoStyle();
        geoStyle.setLineColor(Color.BLUE);
        geoStyle.setLineWidth(1);

        GeoLineM[] routes = pathResult.getRoutes();
        if (routes != null && routes.length > 0) {
            for (GeoLineM route : routes) {
                route.setStyle(geoStyle);
                trackingLayer.add(route, "Route");
            }
            map.refreshTrackingLayer();
        }

        pathGuidesTbl = new JTable();
        DefaultTableModel model = (DefaultTableModel) pathGuidesTbl.getModel();
        model.setColumnIdentifiers(new String[]{"序号", "引导", "耗费", "距离（米）"});
        TableColumnModel columnModel = pathGuidesTbl.getColumnModel();
        columnModel.getColumn(0).setMinWidth(20);
        columnModel.getColumn(1).setMinWidth(20);
        columnModel.getColumn(2).setMinWidth(20);
        columnModel.getColumn(3).setMinWidth(60);
        JScrollPane scrollPane = new JScrollPane(pathGuidesTbl);
        JTabbedPane dataTabPane = new JTabbedPane();
        dataTabPane.addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (popupMenu != null && popupMenu.isVisible()) {
                    popupMenu.setVisible(false);
                }
                switch (e.getButton()) {
                    case MouseEvent.BUTTON1:
                        break;
                    case MouseEvent.BUTTON2:
                        break;
                    case MouseEvent.BUTTON3:
                        popupMenu = new JPopupMenu();
                        JMenuItem closeItem = new JMenuItem("关闭");
                        closeItem.addActionListener(e1 -> {
                            popupMenu.setVisible(false);
                            dataTabPane.remove(scrollPane);
                            if (dataTabPane.getTabCount() == 0) {
                                dataPane.setBottomComponent(null);
                            }
                        });
                        popupMenu.add(closeItem);
                        popupMenu.setLocation(e.getLocationOnScreen());
                        popupMenu.setVisible(true);
                        break;
                }
            }

            @Override
            public void mousePressed(MouseEvent e) {

            }

            @Override
            public void mouseReleased(MouseEvent e) {

            }

            @Override
            public void mouseEntered(MouseEvent e) {

            }

            @Override
            public void mouseExited(MouseEvent e) {

            }
        });
        dataTabPane.addTab("行驶引导", scrollPane);
        dataPane.setBottomComponent(dataTabPane);
        dataPane.setDividerLocation((int) (dataPane.getHeight() * 0.7));

        PathGuide[] pathGuides = pathResult.getPathGuides();
        DefaultTableModel tableModel = (DefaultTableModel) pathGuidesTbl.getModel();
        tableModel.getDataVector().clear();

        if (pathGuides.length > 0) {
            setSize(800, 400);
            tableModel.addRow(new Object[]{"0", "从起点出发", "--", "--"});
            for (PathGuide pathGuide : pathGuides) {
                int pathGuideCount = pathGuide.getCount();
                int index = 1;
                for (int i = 0; i < pathGuideCount; i++) {
                    PathGuideItem pathGuideItem = pathGuide.get(i);
                    Object[] rowData = new Object[4];
                    rowData[0] = index;
                    rowData[1] = generateGuide(pathGuideItem, i == pathGuideCount - 1);
                    if (i == pathGuideCount - 1) {
                        rowData[2] = rowData[3] = "--";
                    } else {
                        rowData[2] = String.format("%.2f", pathGuideItem.getWeight());
                        rowData[3] = String.format("%.2f", pathGuideItem.getLength());
                    }
                    if (!rowData[1].equals(AttrConsts.EMPTY)) {
                        tableModel.addRow(rowData);
                        index++;
                    }
                }
            }
        }
        tableModel.fireTableDataChanged();
        dynamicBtn.setEnabled(true);
    }

    @Override
    protected void doClose() {
        points.clear();
        barrierPoints.clear();
        routePartIndex = 0;
        routePartPointIndex = 0;
        Map map = mapControl.getMap();
        map.getTrackingLayer().clear();
        map.refreshTrackingLayer();
        dataPane.setBottomComponent(null);
        dynamicBtn.setEnabled(false);
    }

    private void addPoint(Point2D mapPoint) {
        points.add(mapPoint);
        GeoPoint geoPoint = new GeoPoint(mapPoint);
        GeoStyle geoStyle = new GeoStyle();
        geoStyle.setMarkerSize(new Size2D(6, 6));
        geoStyle.setFillBackColor(Color.GREEN);
        geoStyle.setFillForeColor(Color.GREEN);
        geoStyle.setLineColor(Color.GREEN);
        geoPoint.setStyle(geoStyle);

        Map map = mapControl.getMap();
        TrackingLayer trackingLayer = map.getTrackingLayer();
        trackingLayer.add(geoPoint, "Points");

        TextPart textPart = new TextPart();
        textPart.setX(geoPoint.getX());
        textPart.setY(geoPoint.getY());
        textPart.setText("站点" + points.getCount());
        GeoText geoText = new GeoText(textPart);
        TextStyle textStyle = new TextStyle();
        textStyle.setForeColor(Color.GREEN);
        geoText.setTextStyle(textStyle);
        trackingLayer.add(geoText, "Points");

        map.refreshTrackingLayer();
    }

    private void addBarrierPoints(Point2D mapPoint) {
        barrierPoints.add(mapPoint);
        GeoPoint geoPoint = new GeoPoint(mapPoint);
        GeoStyle geoStyle = new GeoStyle();
        geoStyle.setMarkerSize(new Size2D(6, 6));
        geoStyle.setFillBackColor(Color.RED);
        geoStyle.setFillForeColor(Color.RED);
        geoStyle.setLineColor(Color.RED);
        geoPoint.setStyle(geoStyle);

        Map map = mapControl.getMap();
        TrackingLayer trackingLayer = map.getTrackingLayer();
        trackingLayer.add(geoPoint, "BarrierPoints");

        TextPart textPart = new TextPart();
        textPart.setX(geoPoint.getX());
        textPart.setY(geoPoint.getY());
        textPart.setText("障碍点" + barrierPoints.getCount());
        GeoText geoText = new GeoText(textPart);
        TextStyle textStyle = new TextStyle();
        textStyle.setForeColor(Color.RED);
        geoText.setTextStyle(textStyle);
        trackingLayer.add(geoText, "BarrierPoints");

        map.refreshTrackingLayer();
    }

    private String generateGuide(PathGuideItem item, boolean isEnd) {
        StringBuilder stringBuilder = new StringBuilder();

        if (item.isStop()) {
            String side = "无";
            if (item.getSideType() == SideType.LEFT)
                side = "左侧";
            if (item.getSideType() == SideType.RIGHT)
                side = "右侧";
            if (item.getSideType() == SideType.MIDDLE)
                side = "道路上";
            String dis = String.format("%.2f", item.getDistance());
            if (item.getIndex() == -1 && item.getID() == -1) {
                return stringBuilder.toString();
            }
            if (!isEnd) {
                stringBuilder.append("到达[").append(item.getIndex()).append("号路由点],在道路").append(side).append(dis).append("米");
            } else {
                stringBuilder.append("到达终点,在道路").append(side).append(dis).append("米");
            }
        }
        // 导引子项为弧段的添加方式
        // If the item is a edge
        if (item.isEdge()) {
            String direct = "直行";
            if (item.getDirectionType() == DirectionType.EAST)
                direct = "东";
            if (item.getDirectionType() == DirectionType.WEST)
                direct = "西";
            if (item.getDirectionType() == DirectionType.SOUTH)
                direct = "南";
            if (item.getDirectionType() == DirectionType.NORTH)
                direct = "北";
            String weight = String.format("%.2f", item.getWeight());
            String roadName = item.getName();
            if (weight.equals("0") && roadName.equals("")) {
                stringBuilder.append("朝").append(direct).append("行走").append(String.format("%.2f", item.getLength())).append("米");
            } else {
                String roadString = roadName.equals("") ? "匿名路段" : roadName;
                stringBuilder.append("沿着[").append(roadString).append("],朝").append(direct).append("行走").append(String.format("%.2f", item.getLength())).append("米");
            }
        }

        return stringBuilder.toString();
    }
}
